package com.quan.api.wx.listener;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.quan.commons.core.utils.AmountUtils;
import com.quan.commons.core.utils.DateUtils;
import com.quan.mall.commons.constant.MallRabbitMQConstant;
import com.quan.mall.entity.*;
import com.quan.mall.service.*;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 消费端-消息队列监听
 * @author yhaoquan
 */

/**
 * 消息队列监听
 * 商场商品订单支付回调业务处理类
 */
@Slf4j
@Component
public class MQListenerWxPayMallGoodsOrderNotify {

    @Autowired
    private OmsOrderService omsOrderService;

    @Autowired
    private OmsOrderGoodsService omsOrderGoodsService;

    @Autowired
    private UmsMemberService umsMemberService;

    @Autowired
    private UmsMemberLevelService umsMemberLevelService;

    @Autowired
    private FmsFinanceCashFlowService fmsFinanceCashFlowService;

    @Autowired
    private FmsMemberCommisionFreezeService fmsMemberCommisionFreezeService;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    // 配置监听器
    @RabbitListener(bindings = @QueueBinding(
            //队列(队列的名称,是否持久化, 对列不存在服务器启动自动创建)
            value = @Queue(value = MallRabbitMQConstant.MALL_QUEUE_PAY_NOTITY, durable = "true"),
            //交换机(交换机的名称,是否持久化,交换机类型, 对列不存在服务器启动自动创建)
            exchange = @Exchange(name = MallRabbitMQConstant.MALL_EVENT_EXCHANGE, durable = "true", type = ExchangeTypes.TOPIC),
            //队列Routiny Key
            key = MallRabbitMQConstant.MALL_ROUTING_KEY_PAY_NOTITY))
    /**
     * 消息处理
     * @param result
     * @param headers
     * @param channel
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    @RabbitHandler
    public void process(@Payload WxPayOrderNotifyResult result, @Headers Map<String, Object> headers, Channel channel) throws Exception {
        log.info("==>微信支付，回调处理开始");

        try {
            OmsOrder order = this.omsOrderService.getOrderByOrderSn(result.getOutTradeNo());

            if (null != order) {

                // 订单商品sku
                List<OmsOrderGoods> goodsList = this.omsOrderGoodsService.getGoodsByOrderSn(order.getOrderSn());

                log.info("下单会员：{}", order.getMemberUsername());
                log.info("订单编号：{}", order.getOrderSn());
                log.info("微信支付订单号：{}", result.getTransactionId());
                log.info("订单总额：{}", order.getTotalAmount());
                log.info("实际支付金额：{}", order.getPayAmount());
                log.info("支付时间：{}", result.getTimeEnd());
                log.info("下单商品-->");
                for (OmsOrderGoods goods : goodsList) {
                    log.info("-->商品价格：{}, 商品数量：{}, 商品名称：{}，购买数量：{}", goods.getSkuPrice(), goods.getSkuNum(), goods.getSkuName(), goods.getSkuNum());
                }
                log.info("微信支付回调结果：{}, {}, {}", result.getReturnCode(), result.getResultCode(), result.getReturnMsg());

                //微信支付通信标识：成功
                if (result.getReturnCode().equals("SUCCESS")) {
                    // 交易状态：成功
                    if (result.getResultCode().equals("SUCCESS")) {
                        log.info("交易状态：成功");
                        ////////////////////////////////////////////////////////////
                        // 业务处理开始
                        ////////////////////////////////////////////////////////////

                        // 获取下单会员
                        final UmsMember member = this.umsMemberService.getById(order.getMemberId());
                        // 下单会员的上级会员
                        final UmsMember refereeMember = this.umsMemberService.getById(member.getRefereeMemberId());

                        // 将上级会员ID和所属供应商ID保存到订单中
                        if(member.getAgentId() != null) {
                            order.setAgentId(member.getAgentId());
                        }
                        if(null != refereeMember) {
                            order.setRefereeMemberId(refereeMember.getId());
                        }

                        // 修改订单状态为：已支付
                        order.setPaymentTime(DateUtils.UDateToLocalDateTime(DateUtil.parse(result.getTimeEnd())));
                        order.setStatus(1);
                        this.omsOrderService.updateById(order);

                        // 资金流水
                        this.saveFmsFlowFundInfo(result, order);

                        // 分销提成
                        this.commisionHandle(result, order);

                    } else {
                        log.error("交易状态：失败");
                    }
                } else {
                    log.error("微信支付通信标识：失败，错误信息：{}", result.getReturnMsg());
                }
            } else {
                log.error("订单不存在，订单编号：[{}]", result.getOutTradeNo());
            }

            log.info(">>>>>>>>>>>>>>>>>>>微信订单支付回调处理结束<<<<<<<<<<<<<<<<<<<");
        } catch (Exception e) {
            e.printStackTrace();
            log.error("==>微信订单支付回调处理发生异常：错误信息：{}", e.getMessage());
        }

        // ACK签收（delivery_tag，是否批量签收）
        channel.basicAck((Long) headers.get(AmqpHeaders.DELIVERY_TAG), false);
        log.info("==>微信支付，回调处理结束");
    }

    /**
     * 分销提成，提成给上级会员（并且上级会员需非游客级别）
     * 会员类型=>游客：无分销提成，普通会员：首单15%，vip会员：首单15%，业务代理：每单15%
     * @param result
     * @param order
     */
    private void commisionHandle(WxPayOrderNotifyResult result, OmsOrder order) {
        log.info("==>分销提成，提成给上级会员");
        // 获取下单会员
        final UmsMember member = this.umsMemberService.getById(order.getMemberId());
        // 获取下单会员的级别
        final UmsMemberLevel level = this.umsMemberLevelService.getById(member.getLevelId());
        // 获取下单用户的购买成功次数
        int buyCount = this.omsOrderService.getMemberBuyCount(order.getMemberId());

        // 下单会员的上级会员
        final UmsMember refereeMember = this.umsMemberService.getById(member.getRefereeMemberId());

        if(null != refereeMember) {
            // 下单会员的上级会员级别
            final UmsMemberLevel refereeLevel = this.umsMemberLevelService.getById(refereeMember.getLevelId());


            if(refereeMember.getType() == 1) { // 游客
                log.info("上级会员级别未达到分销条件，上级会员级别：{}", refereeLevel.getName());

            } else if(refereeMember.getType() == 2) { // 普通会员

                if(buyCount <= 1) { // 首次购买，计算提成
                    log.info("当前下单会员首次购买，计算提成给上级会员");
                    // 下单付款金额
                    final BigDecimal payAmount = order.getPayAmount();
                    log.info("下单付款金额：{}", payAmount);
                    // 上级会员级别的提成百分比
                    final BigDecimal ratio = new BigDecimal(refereeLevel.getDistributionCommission().toString()).divide(new BigDecimal("100"));
                    log.info("上级会员级别的提成百分比：{}", ratio);
                    BigDecimal commissionAmount = payAmount.multiply(ratio).setScale(2, BigDecimal.ROUND_DOWN);
                    log.info("上级会员提成金额：{}", commissionAmount);

                    // 记录到佣金冻结表
                    FmsMemberCommisionFreeze cz = new FmsMemberCommisionFreeze();
                    // 资金类型：1->推广佣金，2->分销佣金
                    cz.setBankrollType(2);
                    cz.setMemberId(refereeMember.getId());
                    cz.setMemberName(refereeMember.getNickname());
                    cz.setSubMemberId(member.getId());
                    cz.setSubMemberName(member.getNickname());

                    cz.setSaleGoodsOrderSn(order.getOrderSn());
                    cz.setSaleGoodsOrderAmount(order.getPayAmount());

                    // 状态：1->待到账，2->已到账，3->锁定（用户申请退款，防止退款时间超过14天），4->已取消(用户14天内申请退款，佣金扣除不到账)
                    cz.setStatus(3);
                    cz.setCommissionPercent(ratio);
                    cz.setFreezeAmount(commissionAmount);
                    // 是否可提现：1->可提现，2->不可提现
                    cz.setIsWithdraw(1);
                    cz.setRemarks("上级会员当前级别：["+refereeLevel.getName()+"]");
                    this.fmsMemberCommisionFreezeService.save(cz);

                    log.info("==>分销提成完成");
                } else {
                    log.info("当前下单会员非首次购买，无需计算提成给上级会员");
                }


            } else if(refereeMember.getType() == 3) { // vip会员

                if(buyCount <= 1) { // 首次购买，计算提成
                    log.info("当前下单会员首次购买，计算提成给上级会员");
                    // 下单付款金额
                    final BigDecimal payAmount = order.getPayAmount();
                    log.info("下单付款金额：{}", payAmount);
                    // 上级会员级别的提成百分比
                    final BigDecimal ratio = new BigDecimal(refereeLevel.getDistributionCommission().toString()).divide(new BigDecimal("100"));
                    log.info("上级会员级别的提成百分比：{}", ratio);
                    BigDecimal commissionAmount = payAmount.multiply(ratio).setScale(2, BigDecimal.ROUND_DOWN);
                    log.info("上级会员提成金额：{}", commissionAmount);

                    // 记录到佣金冻结表
                    FmsMemberCommisionFreeze cz = new FmsMemberCommisionFreeze();
                    // 资金类型：1->推广佣金，2->分销佣金
                    cz.setBankrollType(2);
                    cz.setMemberId(refereeMember.getId());
                    cz.setMemberName(refereeMember.getNickname());
                    cz.setSubMemberId(member.getId());
                    cz.setSubMemberName(member.getNickname());

                    cz.setSaleGoodsOrderSn(order.getOrderSn());
                    cz.setSaleGoodsOrderAmount(order.getPayAmount());

                    // 状态：1->待到账，2->已到账，3->锁定（用户申请退款，防止退款时间超过14天），4->已取消(用户14天内申请退款，佣金扣除不到账)
                    cz.setStatus(3);
                    cz.setCommissionPercent(ratio);
                    cz.setFreezeAmount(commissionAmount);
                    // 是否可提现：1->可提现，2->不可提现
                    cz.setIsWithdraw(1);
                    cz.setRemarks("上级会员当前级别：["+refereeLevel.getName()+"]");
                    this.fmsMemberCommisionFreezeService.save(cz);
                    log.info("==>分销提成完成");

                } else {
                    log.info("当前下单会员非首次购买，无需计算提成给上级会员");
                }

            } else if(refereeMember.getType() == 8) { // 砖石会员

                if(buyCount <= 1) { // 首次购买，计算提成
                    log.info("当前下单会员首次购买，计算提成给上级会员");
                    // 下单付款金额
                    final BigDecimal payAmount = order.getPayAmount();
                    log.info("下单付款金额：{}", payAmount);
                    // 上级会员级别的提成百分比
                    final BigDecimal ratio = new BigDecimal(refereeLevel.getDistributionCommission().toString()).divide(new BigDecimal("100"));
                    log.info("上级会员级别的提成百分比：{}", ratio);
                    BigDecimal commissionAmount = payAmount.multiply(ratio).setScale(2, BigDecimal.ROUND_DOWN);
                    log.info("上级会员提成金额：{}", commissionAmount);

                    // 记录到佣金冻结表
                    FmsMemberCommisionFreeze cz = new FmsMemberCommisionFreeze();
                    // 资金类型：1->推广佣金，2->分销佣金
                    cz.setBankrollType(2);
                    cz.setMemberId(refereeMember.getId());
                    cz.setMemberName(refereeMember.getNickname());
                    cz.setSubMemberId(member.getId());
                    cz.setSubMemberName(member.getNickname());

                    cz.setSaleGoodsOrderSn(order.getOrderSn());
                    cz.setSaleGoodsOrderAmount(order.getPayAmount());

                    // 状态：1->待到账，2->已到账，3->锁定（用户申请退款，防止退款时间超过14天），4->已取消(用户14天内申请退款，佣金扣除不到账)
                    cz.setStatus(3);
                    cz.setCommissionPercent(ratio);
                    cz.setFreezeAmount(commissionAmount);
                    // 是否可提现：1->可提现，2->不可提现
                    cz.setIsWithdraw(1);
                    cz.setRemarks("上级会员当前级别：["+refereeLevel.getName()+"]");
                    this.fmsMemberCommisionFreezeService.save(cz);
                    log.info("==>分销提成完成");

                } else {
                    log.info("当前下单会员非首次购买，无需计算提成给上级会员");
                }

            } else if(refereeMember.getType() == 4) { // 业务代理（下级会员购买成功，每次都有提成）

                log.info("当前下单会员首次购买，计算提成给上级会员");
                // 下单付款金额
                final BigDecimal payAmount = order.getPayAmount();
                log.info("下单付款金额：{}", payAmount);
                // 上级会员级别的提成百分比
                final BigDecimal ratio = new BigDecimal(refereeLevel.getDistributionCommission().toString()).divide(new BigDecimal("100"));
                log.info("上级会员级别的提成百分比：{}", ratio);
                BigDecimal commissionAmount = payAmount.multiply(ratio).setScale(2, BigDecimal.ROUND_DOWN);
                log.info("上级会员提成金额：{}", commissionAmount);

                // 记录到佣金冻结表
                FmsMemberCommisionFreeze cz = new FmsMemberCommisionFreeze();
                // 资金类型：1->推广佣金，2->分销佣金
                cz.setBankrollType(2);
                cz.setMemberId(refereeMember.getId());
                cz.setMemberName(refereeMember.getNickname());
                cz.setSubMemberId(member.getId());
                cz.setSubMemberName(member.getNickname());

                cz.setSaleGoodsOrderSn(order.getOrderSn());
                cz.setSaleGoodsOrderAmount(order.getPayAmount());

                // 状态：1->待到账，2->已到账，3->锁定（用户申请退款，防止退款时间超过14天），4->已取消(用户14天内申请退款，佣金扣除不到账)
                cz.setStatus(3);
                cz.setCommissionPercent(ratio);
                cz.setFreezeAmount(commissionAmount);
                // 是否可提现：1->可提现，2->不可提现
                // 会员为业务代理，则不可提现
                cz.setIsWithdraw(2);
                cz.setRemarks("上级会员当前级别：["+refereeLevel.getName()+"]");
                this.fmsMemberCommisionFreezeService.save(cz);
                log.info("==>分销提成完成");
            } else if(refereeMember.getType() == 9) { // 分销商（下级会员购买成功，每次都有提成）

                log.info("当前下单会员首次购买，计算提成给上级会员");
                // 下单付款金额
                final BigDecimal payAmount = order.getPayAmount();
                log.info("下单付款金额：{}", payAmount);
                // 上级会员级别的提成百分比
                final BigDecimal ratio = new BigDecimal(refereeLevel.getDistributionCommission().toString()).divide(new BigDecimal("100"));
                log.info("上级会员级别的提成百分比：{}", ratio);
                BigDecimal commissionAmount = payAmount.multiply(ratio).setScale(2, BigDecimal.ROUND_DOWN);
                log.info("上级会员提成金额：{}", commissionAmount);

                // 记录到佣金冻结表
                FmsMemberCommisionFreeze cz = new FmsMemberCommisionFreeze();
                // 资金类型：1->推广佣金，2->分销佣金
                cz.setBankrollType(2);
                cz.setMemberId(refereeMember.getId());
                cz.setMemberName(refereeMember.getNickname());
                cz.setSubMemberId(member.getId());
                cz.setSubMemberName(member.getNickname());

                cz.setSaleGoodsOrderSn(order.getOrderSn());
                cz.setSaleGoodsOrderAmount(order.getPayAmount());

                // 状态：1->待到账，2->已到账，3->锁定（用户申请退款，防止退款时间超过14天），4->已取消(用户14天内申请退款，佣金扣除不到账)
                cz.setStatus(3);
                cz.setCommissionPercent(ratio);
                cz.setFreezeAmount(commissionAmount);
                // 是否可提现：1->可提现，2->不可提现
                // 会员为业务代理，则不可提现
                cz.setIsWithdraw(2);
                cz.setRemarks("上级会员当前级别：["+refereeLevel.getName()+"]");
                this.fmsMemberCommisionFreezeService.save(cz);
                log.info("==>分销提成完成");
            }

        } else {
            log.info("当前下单会员无上级会员，无需分销提成");
        }
    }

    /**
     * 资金流水
     * @param result
     * @param order
     */
    private void saveFmsFlowFundInfo(WxPayOrderNotifyResult result, OmsOrder order) {
        // 订单商品sku
        List<OmsOrderGoods> goodsList = this.omsOrderGoodsService.getGoodsByOrderSn(order.getOrderSn());
        for (OmsOrderGoods goods : goodsList) {

            FmsFinanceCashFlow cashFlow = new FmsFinanceCashFlow();
            cashFlow.setOpenId(result.getOpenid());
            cashFlow.setAppId(result.getAppid());
            cashFlow.setMchId(result.getMchId());
            cashFlow.setMemberId(order.getMemberId());
            cashFlow.setMemberName(order.getMemberUsername());
            cashFlow.setTransactionId(result.getTransactionId());

            // 订单信息
            cashFlow.setOrderId(order.getId());
            cashFlow.setOrderSn(order.getOrderSn());
            cashFlow.setGoodsId(goods.getId());
            cashFlow.setGoodsSkuId(goods.getSkuId());

            // 订单支付
            cashFlow.setTransactionType(1);
            cashFlow.setAmount(goods.getRealAmount());
            cashFlow.setRemarks("商品购买：" + goods.getSkuName());

            Map<String, Object> extraMap = new HashMap<String, Object>();
            cashFlow.setExtraJson(JSON.toJSONString(extraMap));

            this.fmsFinanceCashFlowService.save(cashFlow);

        }
    }


}
